package com.example.mylogin.handler;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKBReader;
import org.locationtech.jts.io.WKBWriter;
import java.sql.*;

/**
 * 自定义MyBatis类型处理器，用于处理Geometry类型的数据
 */
public class JtsGeometryTypeHandler extends BaseTypeHandler<Geometry> {
    // 使用WKB(Well-Known Binary)格式的读取器和写入器来处理Geometry对象与字节之间的转换
    private static final WKBReader wkbReader = new WKBReader();
    private static final WKBWriter wkbWriter = new WKBWriter();

    /**
     * 设置非空参数到PreparedStatement中。
     * 将Geometry对象通过WKBWriter序列化为字节数组，并设置到数据库中。
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Geometry parameter, JdbcType jdbcType) throws SQLException {
        ps.setBytes(i, wkbWriter.write(parameter));
    }

    /**
     * 从ResultSet中获取指定列名的几何数据，并解析为Geometry对象。
     */
    @Override
    public Geometry getNullableResult(ResultSet rs, String columnName) throws SQLException {
        byte[] bytes = rs.getBytes(columnName); // 获取列的字节数据
        return parseBytes(bytes); // 调用parseBytes方法解析字节并返回Geometry对象
    }

    /**
     * 从ResultSet中获取指定列索引的几何数据，并解析为Geometry对象。
     */
    @Override
    public Geometry getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        byte[] bytes = rs.getBytes(columnIndex); // 获取列的字节数据
        return parseBytes(bytes); // 调用parseBytes方法解析字节并返回Geometry对象
    }

    /**
     * 从CallableStatement中获取指定列索引的几何数据，并解析为Geometry对象。
     */
    @Override
    public Geometry getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        byte[] bytes = cs.getBytes(columnIndex); // 获取列的字节数据
        return parseBytes(bytes); // 调用parseBytes方法解析字节并返回Geometry对象
    }

    /**
     * 解析字节数组为Geometry对象。
     * 如果字节数组为空，直接返回null；
     * 否则使用WKBReader将字节数据反序列化为Geometry对象。
     * 若解析失败，则抛出运行时异常。
     */
    private Geometry parseBytes(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        try {
            return wkbReader.read(bytes);
        } catch (ParseException e) {
            throw new RuntimeException("Failed to parse geometry", e);
        }
    }
}
